package com.ljw.punishment.baserule;

import com.alibaba.fastjson.JSONObject;
import com.google.common.base.Objects;
import com.ljw.punishment.customBiDuifunction.CustomFunction;
import com.ljw.punishment.mvelcondition.CustomAction;
import com.ljw.punishment.mvelcondition.CustomMvelCondition;
import com.ljw.punishment.mvelcondition.CustomStrAction;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.jeasy.rules.api.Facts;
import org.jeasy.rules.core.BasicRule;
import org.mvel2.ParserContext;

import java.io.Serializable;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @author lijunwei
 * @date 2025/5/21
 */
@Slf4j
@Data
public class CommonRule extends BasicRule implements Serializable {
    private static final long serialVersionUID = -5585609939143299413L;

    private CustomMvelCondition condition;
    private final List<CustomAction> actions = new ArrayList<>();
    private final ParserContext parserContext;

    private Map<Integer, Facts> result = null;

    /**
     * 规则id
     */
    private Integer id;

    private String name;

    private String description;

    private int priority;

    /**
     * 规则内容
     */
    private String ruleContext;

    /**
     * 规则组id
     */
    private Integer ruleGroupId;

    /**
     * 奖惩code
     */
    private String rewardCode;

    public CommonRule(String name, String desc, Integer priority, Map<Integer, Facts> result) {
        super(name, desc, priority);
        this.parserContext = initParseContext();
        this.result = result;
        this.name = name;
        this.description = desc;
        this.priority = priority;
    }

    public CommonRule(String name, String desc, Integer priority) {
        super(name, desc, priority);
        this.parserContext = new ParserContext();
        this.result = new HashMap<>();
        this.name = name;
        this.description = desc;
        this.priority = priority;
    }

    public ParserContext initParseContext() {
        ParserContext ctx = new ParserContext();
        Method[] declaredMethods = CustomFunction.class.getDeclaredMethods();
        for (Method declaredMethod : declaredMethods) {
            ctx.addImport(declaredMethod.getName(), declaredMethod);
        }
        return ctx;
    }

    public CommonRule when(String condition, Map<String, Object> extendParam) {
        this.condition = new CustomMvelCondition(condition, initParseContext(), extendParam);
        return this;
    }

    public CommonRule when(String condition) {
        this.condition = new CustomMvelCondition(condition, initParseContext());
        return this;
    }

    public CommonRule then(String action) {
        if (StringUtils.isBlank(action)) {
            return this;
        }
        this.actions.add(new CustomStrAction(action));
        return this;
    }

    @Override
    public boolean evaluate(Facts facts) {
        return condition.evaluate(facts);
    }

    @Override
    public void execute(Facts facts) throws Exception {
        log.info("事实对象 facts :{} , 命中规则 rewardCode :{} ,ruleId:{} , ruleName:{}", JSONObject.toJSONString(facts), this.getRewardCode(), id, name);
        if (CollectionUtils.isNotEmpty(this.actions)) {
            result.put(id, facts);
        }
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) {
            return true;
        }
        if (o == null || getClass() != o.getClass()) {
            return false;
        }
        if (!super.equals(o)) {
            return false;
        }
        CommonRule that = (CommonRule) o;
        return priority == that.priority && Objects.equal(condition, that.condition)
                && Objects.equal(actions, that.actions) && Objects.equal(parserContext, that.parserContext)
                && Objects.equal(result, that.result) && Objects.equal(id, that.id) && Objects.equal(name, that.name)
                && Objects.equal(description, that.description) && Objects.equal(ruleContext, that.ruleContext)
                && Objects.equal(ruleGroupId, that.ruleGroupId) && Objects.equal(rewardCode, that.rewardCode);
    }

    @Override
    public int hashCode() {
        return Objects.hashCode(super.hashCode(), condition, actions, parserContext, result, id, name, description,
                priority, ruleContext, ruleGroupId, rewardCode);
    }

    @Override
    public String toString() {
        return "CommonRule{" + "condition=" + condition + ", actions=" + actions + ", parserContext=" + parserContext
                + ", result=" + result + ", id=" + id + ", name='" + name + '\'' + ", description='" + description
                + '\'' + ", priority=" + priority + ", ruleContext='" + ruleContext + '\'' + ", ruleGroupId="
                + ruleGroupId + ", rewardCode='" + rewardCode + '\'' + '}';
    }

}

